﻿#ifndef _VARIANT_H_H_
#define _VARIANT_H_H_

#include "kernel/observer_ptr.h"
#include "kernel/OgreDataStream.h"
#include "kernel/time/time.h"

namespace FD
{
	namespace Kernel
	{
		class Time;
		//class MemoryDataStreamPtr;
		class CVariantPrivate;

		class FD_Kernel_Export Variant : public FD::Kernel::CReferenced
		{
		public:
			enum DataType
			{
				DT_Unknown				= 0,
				DT_Bool					= 1,
				DT_UInt32				= 2,
				DT_Int32				= 3,
				DT_UInt64				= 4,
				DT_Int64				= 5,
				DT_Real32				= 6,
				DT_Real64				= 7,
				DT_String				= 8,
				DT_WString				= 9,
				DT_Time					= 10,
				DT_MemoryDataStream		= 11,
				DT_UserType            =12
			};

			Variant();
			Variant(const Variant &other);
			~Variant();

			explicit Variant(bool boolval)	{init();fromBool(boolval);}
			Variant(INT32 int32val )	{init();fromInt32(int32val);}
			Variant(INT64  int64val)	{init();fromInt64(int64val);}
			Variant(UINT64  uint64val)	{init();fromUInt64(uint64val);}
			Variant(float real32val)	{init();fromReal32(real32val);}
			Variant(double real64val)	{init();fromReal64(real64val);}
			Variant(const FD::Kernel::Time& ctval )	{init();fromDateTime(ctval);}
			Variant(const CHAR* charval)	{init();fromString(charval);}
			Variant(const void* userdata);/////存用户自定义类型
		public:
			Variant(const WCHAR* val)	{init();fromWString(val);}
			Variant(UINT32  val)	{init();fromUInt32(val);}
		public:
			Variant(const FD::Kernel::FdMultiByteString &stringval)	{init();fromString(stringval);}	
			Variant(const FD::Kernel::MemoryDataStreamPtr &mdspval)	{init();fromDataStream(mdspval);}

			void clear();
			bool isNull() const;
			bool isValid() const;
			FD::Kernel::Variant::DataType type() const;
			void* data();
			const void* constData() const;
			/////inline const void* data() const {constData();}
		public:
			bool toBool(bool *ok/*=0*/) const;
			bool toBool()const{ return toBool((bool*)0); }
			INT32 toInt32(bool *ok/*=0*/) const;
			INT32 toInt32() const{ return toInt32((bool*)0);}
			UINT32 toUInt32(bool *ok/*=0*/) const;
			UINT32 toUInt32() const{ return toUInt32((bool*)0);}
			INT64 toInt64(bool *ok/*=0*/) const;
			INT64 toInt64() const{ return toInt64((bool*)0);}
			UINT64 toUInt64(bool *ok/*=0*/) const;
			UINT64 toUInt64() const{ return toUInt64((bool*)0);}
			float toReal32(bool *ok/*=0*/) const;
			float toReal32() const{ return toReal32((bool*)0);}
			double toReal64(bool *ok/*=0*/) const;
			double toReal64() const{ return toReal64((bool*)0);}
			FD::Kernel::Time toDateTime() const;
			FD::Kernel::FdMultiByteString toString() const;
			FD::Kernel::FdUnicodeString toWString() const;
			FD::Kernel::MemoryDataStreamPtr toDataStream() const;

			void fromBool(bool val);
			void fromInt32(INT32 val);
			void fromUInt32(UINT32 val);
			void fromInt64(INT64 val);
			void fromUInt64(UINT64 val);
			void fromReal32(float val);
			void fromReal64(double val);
			void fromDateTime(const FD::Kernel::Time& val);
			void fromString(const FD::Kernel::FdMultiByteString& val);
			void fromWString(const FD::Kernel::FdUnicodeString& val);
			void fromDataStream(const FD::Kernel::MemoryDataStreamPtr &val);
			void fromCharString(const CHAR* val);
			void fromWCharString(const WCHAR* val);
			FD::Kernel::Variant& operator=(const FD::Kernel::Variant &other);

			bool operator==(const FD::Kernel::Variant &other) const;
			bool operator!=(const FD::Kernel::Variant &other) const {return !(*this==other);}

		private:
			void init();
			void detach();
			CVariantPrivate *m_private;

		public:
			Variant(const FD::Kernel::FdUnicodeString &val)	{init();fromWString(val);}
		};

		class FD_Kernel_Export VariantArray : public FD::Kernel::CReferenced
		{
		public:
			typedef bool (*Predict) (const FD::Kernel::Variant &var1,const FD::Kernel::Variant &var2);
			void sort(Predict pred);

		public:
			VariantArray(){}
			INT32 count() const;
			FD::Kernel::Variant at(INT32 index);
			FD::Kernel::Variant take(INT32 index);

			INT32 find(FD::Kernel::Variant var,UINT32 from/*=0*/) const;
			INT32 find(FD::Kernel::Variant var) const { return find(var, 0);}

			void prepend(FD::Kernel::Variant var);
			void insert(INT32 index,FD::Kernel::Variant var);
			void append(FD::Kernel::Variant var);
			void append(const FD::Kernel::VariantArray &other);

			void erase(INT32 index);

			void swap(INT32 first,INT32 second);

			bool isEmpty() const;
			void clear();

			FD::Kernel::VariantArray& operator=(const FD::Kernel::VariantArray& other);
			FD::Kernel::VariantArray& operator+=(const FD::Kernel::VariantArray& other);
			FD::Kernel::VariantArray operator+(const FD::Kernel::VariantArray& other);

			FD::Kernel::Variant& operator[](INT32 i);
			FD::Kernel::Variant operator[](INT32 i) const;

			FD::Kernel::Variant& operator[](UINT32 i);
			FD::Kernel::Variant operator[](UINT32 i) const;

		private:
			std::vector<FD::Kernel::Variant> m_vars;
		};
	}
}

#endif ////_VARIANT_H_H_

